﻿using System;
using System.Runtime.InteropServices;
using ProdControls.NativePatterns.MessageConstants;
using ProdUI.Hook.NativePatterns;

namespace ProdControls.Utility
{

    #region Union Structs for SendInput Call

    /// <summary>
    ///   Contains information about a simulated mouse event
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct MOUSEINPUT
    {
        /// <summary>
        ///   The absolute position of the mouse, or the amount of motion since the last mouse event was generated, depending on the value of the dwFlags member.
        ///   Absolute data is specified as the x coordinate of the mouse; relative data is specified as the number of pixels moved
        /// </summary>
        [MarshalAs(UnmanagedType.I4)] public int DX;

        /// <summary>
        ///   The absolute position of the mouse, or the amount of motion since the last mouse event was generated, depending on the value of the dwFlags member.
        ///   Absolute data is specified as the x coordinate of the mouse; relative data is specified as the number of pixels moved
        /// </summary>
        [MarshalAs(UnmanagedType.I4)] public int DY;

        /// <summary>
        ///   Depending of the dwFlags value, it contains different things. http://msdn.microsoft.com/en-us/library/ms646273(v=VS.85).aspx
        /// </summary>
        [MarshalAs(UnmanagedType.I4)] public int MouseData;

        /// <summary>
        ///   <see cref="MOUSEEVENTF" />
        /// </summary>
        [MarshalAs(UnmanagedType.I4)] public int DWFlags;

        /// <summary>
        ///   The time stamp for the event, in milliseconds. If this parameter is 0, the system will provide its own time stamp
        /// </summary>
        [MarshalAs(UnmanagedType.I4)] public int Time;

        /// <summary>
        ///   An additional value associated with the mouse event. An application calls GetMessageExtraInfo to obtain this extra information
        /// </summary>
        public IntPtr DWExtraInfo;
    };

    /// <summary>
    ///   Contains information about a simulated keyboard event. Since this isn't used yet, its taking up space for the INPUT struct
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct KEYBDINPUT
    {
        /// <summary>
        ///   A virtual-key code. The code must be a value in the range 1 to 254. If the dwFlags member specifies KEYEVENTF_UNICODE, wVk must be 0.
        /// </summary>
        public int WVK;

        /// <summary>
        ///   A hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies a Unicode character which is to be sent to the foreground application.
        /// </summary>
        public int WScan;

        /// <summary>
        ///   Specifies various aspects of a keystroke. We don't use this (yet) so I havent created the enumeration for it
        /// </summary>
        public int DWFlags;

        /// <summary>
        ///   The time stamp for the event, in milliseconds. If this parameter is zero, the system will provide its own time stamp.
        /// </summary>
        public int Time;

        /// <summary>
        ///   An additional value associated with the keystroke. Use the GetMessageExtraInfo function to obtain this information
        /// </summary>
        public IntPtr DWExtraInfo;
    };

    /// <summary>
    ///   Contains information about a simulated message generated by an input device other than a keyboard or mouse.Since this isn't used yet, its taking up space for the INPUT struct
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct HARDWAREINPUT
    {
        /// <summary>
        ///   The message generated by the input hardware
        /// </summary>
        public int UMsg;

        /// <summary>
        ///   The low-order word of the lParam parameter for uMsg
        /// </summary>
        public int WParamL;

        /// <summary>
        ///   The high-order word of the lParam parameter for uMsg
        /// </summary>
        public int WParamH;
    }

    /// <summary>
    ///   contains the mi, ki and hi structs for the input struct.
    /// </summary>
    /// <remarks>
    ///   These are laid out per MSDN INPUT structure documentation in order to simulate a c union
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    internal struct UNION
    {
        public MOUSEINPUT MouseInput;
        public KEYBDINPUT KeyboardInput;
        public HARDWAREINPUT HardwareInput;
    };

    /// <summary>
    ///   Used by SendInput to store information for synthesizing input events such as keystrokes, mouse movement, and mouse clicks
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct NPUT
    {
        /// <summary>
        ///   The type of the input event <see cref="InputStructType" />
        /// </summary>
        public int Type;

        /// <summary>
        ///   Union of structs <see cref="UNION" />
        /// </summary>
        public UNION Union;
    };

    /// <summary>
    ///   Used for the INPUT structure
    /// </summary>
    internal enum InputStructType
    {
        /// <summary>
        ///   The event is a mouse event. Use the mi structure of the union.
        /// </summary>
        InputMouse,

        /// <summary>
        ///   The event is a keyboard event. Use the ki structure of the union.
        /// </summary>
        InputKeyboard,

        /// <summary>
        ///   The event is a hardware event. Use the hi structure of the union.
        /// </summary>
        InputHardware
    }

    #endregion Union Structs for SendInput Call

    /// <summary>
    ///   Contains information about the placement of a window on the screen.
    /// </summary>
    internal struct WindowPlacement
    {
        /// <summary>
        ///   The flags that control the position of the minimized window and the method by which the window is restored.
        /// </summary>
        [MarshalAs(UnmanagedType.U4)] internal WindowPlacementFlags Flags;

        /// <summary>
        ///   The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT)
        /// </summary>
        [MarshalAs(UnmanagedType.U4)] internal uint Length;

        /// <summary>
        ///   The coordinates of the window's upper-left corner when the window is maximized.
        /// </summary>
        [MarshalAs(UnmanagedType.U4)] internal uint PtMaxPosition;

        /// <summary>
        ///   The coordinates of the window's upper-left corner when the window is minimized
        /// </summary>
        [MarshalAs(UnmanagedType.U4)] internal uint PtMinPosition;

        /// <summary>
        ///   The window's coordinates when the window is in the restored position.
        /// </summary>
        [MarshalAs(UnmanagedType.U4)] internal uint RcNormalPosition;

        /// <summary>
        ///   The current show state of the window. This member can be one of the following values.
        /// </summary>
        [MarshalAs(UnmanagedType.U4)] internal ShowCmdFlags ShowCmd;
    }

    /// <summary>
    ///   The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle
    /// </summary>
    internal struct RECT
    {
        /// <summary>
        ///   The y-coordinate of the lower-right corner of the rectangle
        /// </summary>
        internal int Bottom;

        /// <summary>
        ///   The x-coordinate of the upper-left corner of the rectangle.
        /// </summary>
        internal int Left;

        /// <summary>
        ///   The x-coordinate of the lower-right corner of the rectangle.
        /// </summary>
        internal int Right;

        /// <summary>
        ///   The y-coordinate of the upper-left corner of the rectangle.
        /// </summary>
        internal int Top;
    }

    /// <summary>
    ///   constant values used to describe the state of objects in an application UI.
    /// </summary>
    internal enum ObjectStateConstants
    {
        STATE_SYSTEM_UNAVAILABLE = 0x00000001, // Disabled
        STATE_SYSTEM_SELECTED = 0x00000002,
        STATE_SYSTEM_FOCUSED = 0x00000004,
        STATE_SYSTEM_PRESSED = 0x00000008,
        STATE_SYSTEM_CHECKED = 0x00000010,
        STATE_SYSTEM_MIXED = 0x00000020, // 3-state checkbox or toolbar button
        STATE_SYSTEM_INDETERMINATE = STATE_SYSTEM_MIXED,
        STATE_SYSTEM_READONLY = 0x00000040,
        STATE_SYSTEM_HOTTRACKED = 0x00000080,
        STATE_SYSTEM_DEFAULT = 0x00000100,
        STATE_SYSTEM_EXPANDED = 0x00000200,
        STATE_SYSTEM_COLLAPSED = 0x00000400,
        STATE_SYSTEM_BUSY = 0x00000800,
        STATE_SYSTEM_FLOATING = 0x00001000, // Children "owned" not "contained" by parent
        STATE_SYSTEM_MARQUEED = 0x00002000,
        STATE_SYSTEM_ANIMATED = 0x00004000,
        STATE_SYSTEM_INVISIBLE = 0x00008000,
        STATE_SYSTEM_OFFSCREEN = 0x00010000,
        STATE_SYSTEM_SIZEABLE = 0x00020000,
        STATE_SYSTEM_MOVEABLE = 0x00040000,
        STATE_SYSTEM_SELFVOICING = 0x00080000,
        STATE_SYSTEM_FOCUSABLE = 0x00100000,
        STATE_SYSTEM_SELECTABLE = 0x00200000,
        STATE_SYSTEM_LINKED = 0x00400000,
        STATE_SYSTEM_TRAVERSED = 0x00800000,
        STATE_SYSTEM_MULTISELECTABLE = 0x01000000, // Supports multiple selection
        STATE_SYSTEM_EXTSELECTABLE = 0x02000000, // Supports extended selection
        STATE_SYSTEM_ALERT_LOW = 0x04000000, // This information is of low priority
        STATE_SYSTEM_ALERT_MEDIUM = 0x08000000, // This information is of medium priority
        STATE_SYSTEM_ALERT_HIGH = 0x10000000, // This information is of high priority
        STATE_SYSTEM_PROTECTED = 0x20000000, // access to this is restricted
        STATE_SYSTEM_VALID = 0x3FFFFFFF
    }

    // ReSharper restore InconsistentNaming
}